package com.gree.flowable.modeler.security;

import org.flowable.ui.common.security.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @description: 重写 spring-security 相关模块
 * <p>在源码在源码中 org.flowable.ui.modeler.conf.SecurityConfiguration 为流程设计器的权限核心控制，</p>
 * <p>所以需要 进行改造。本处直接基于spring-security 的运行机制重写相关的实现类，不引用原始配置的相关信息</p>
 */
@Component
@WebFilter(urlPatterns = {"/app/**", "/api/**"})
public class MyFilter extends OncePerRequestFilter {
    /**
     * PS: 经过试验，过滤器必须继承于 org.springframework.web.filter.OncePerRequestFilter
     * 而不能直接实现 javax.servlet.Filter ，不然就算注入到 spring-security容器中，
     * 也不能触发本身的权限校验，具体原理还有待研究。此处参考源码中的 org.flowable.ui.common.filter.FlowableCookieFilter进行改造
     */
    private Logger LOGGER = LoggerFactory.getLogger(MyFilter.class);

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        if (skipAuthenticationCheck(request)) {
            filterChain.doFilter(request, response);
            return;
        }

        LOGGER.debug("MyFilter:doFilterInternal:" + request.getRequestURL());

        if (request.getRequestURI().startsWith("/rest/")) {
            /**
             * 这里原来为破解flowable前端登录，自定义的token，现在为微服务化flowable不进行定制化。
             * 主要是这个SecurityUtils一开始没打算用commons模块
             */
            LOGGER.debug("MyFilter:doFilterInternal:校验......");
            String clientId = com.gree.framework.utils.SecurityUtils.getClientId();
            String systemName = null;
            switch (clientId) {
                case "gscm_client":
                    systemName = "admin";
                    break;
                case "external_client":
                    systemName = com.gree.framework.utils.SecurityUtils.getUser().getUsername();
                    break;
                case "external_client1":
                    systemName = com.gree.framework.utils.SecurityUtils.getUser().getUsername();
                    break;
                default:
            }
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(systemName, "");
            SecurityContextHolder.getContext().setAuthentication(token);
        } else {
            LOGGER.debug("MyFilter:doFilterInternal:校验通过.......");
        }

        filterChain.doFilter(request, response);
    }

    protected boolean skipAuthenticationCheck(HttpServletRequest request) {

        if (request.getRequestURI().endsWith("/swagger-ui.html")) {
            LOGGER.info("swagger处理");
            return false;
        }

        return request.getRequestURI().endsWith(".css") ||
                request.getRequestURI().endsWith(".js") ||
                request.getRequestURI().endsWith(".html") ||
                request.getRequestURI().endsWith(".map") ||
                request.getRequestURI().endsWith(".woff") ||
                request.getRequestURI().endsWith(".png") ||
                request.getRequestURI().endsWith(".jpg") ||
                request.getRequestURI().endsWith(".jpeg") ||
                request.getRequestURI().endsWith(".tif") ||
                request.getRequestURI().endsWith(".tiff");
    }

}